Snyk IaCでTerraformのドリフト検出をやってみた
こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。
今回は、snyk iac describe
コマンドを利用して、Terraformで作ったリソースのドリフト検出をしてみようと思います。
Snyk IaC describeコマンドとは
snyk iac describe
では次の2つを検出できるコマンドです。Terraformのtfstate内のリソースとクラウドプロバイダーの実際のリソースを比較して検出するため、CloudFormationで書かれたファイルには使えません。
- ドリフト(現在の状態とtfstateとの差異を検出)
- 該当リソースがIaC(Terraform)で管理されているかどうかを検出
今回は1つめのドリフトを検出してみようと思います。
やってみた
今回は次のコードを使用してドリフト検出を試してみようと思います。
注目いただきたいのが、「enable_dns_hostnames
」と「enable_dns_support
」です。「enable_dns_hostnames
」はデフォルトがfalseのため、コードでtrueに変更しました。対して、「enable_dns_support
」はデフォルトでtrueのため、設定を省略したケースを想定しています。(コードは便宜上コメントアウトで表現しています。)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.27.0"
}
}
backend "s3" {
bucket = "tf-takakuni"
key = "snyk_iac/terraform.tfstate"
region = "ap-northeast-1"
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true # default:false
# enable_dns_support = true # default:true
tags = {
"Name" = "snyk-iac-vpc"
}
}
手動変更
作成したVPCに対して手動変更を行います。先ほどの、「enable_dns_hostnames
」と「enable_dns_support
」に対応した「DNS ホスト名」と「DNS 解決」を無効に設定します。
ドリフト検出
実際にsnyk iac describe
コマンドを使用してみます。デフォルトではコマンドを実行したフォルダ配下を管理しているtfstateのありかを探して差分を検出します。
また、AWSプロバイダーの場合、デフォルトでは「3.19.0」のバージョンでドリフトを検出するため今回使用している「4.27.0」にバージョンを合わせて実行します。
snyk iac describe --drift --tf-provider-version=4.27.0
実行結果は次の通りに出力されました。「enable_dns_hostnames
」と「enable_dns_support
」のどちらもドリフトとして検出されました。
takakuni@snyk_iac % snyk iac describe --drift --tf-provider-version=4.27.0
Using Terraform state tfstate+s3://tf-takakuni/snyk_iac/terraform.tfstate found in main.tf. Use the --from flag to specify another state file.
Scanned states (1)
Scan duration: 21s
Provider version used to scan: 4.27.0. Use --tf-provider-version to use another version.
Snyk Scanning Infrastructure As Code Discrepancies...
Info: Resources under IaC, but different to terraform states.
Resolve: Reapply IaC resources or update into terraform.
Changed resources: 1
State: tfstate+s3://tf-takakuni/snyk_iac/terraform.tfstate [ Changed Resources: 1 ]
Resource Type: aws_vpc
ID: vpc-0dd5115c64147afd6
~ enable_dns_hostnames: true => false
~ enable_dns_support: true => false
Test Summary
Managed Resources: 1
Changed Resources: 1
IaC Coverage: 100%
Info: To reach full coverage, remove resources or move it to Terraform.
Tip: Run --help to find out about commands and flags.
Scanned with aws provider version 4.27.0. Use --tf-provider-version to update.
(補足)検出範囲について
普段、CloudFormationのドリフト検出機能をご利用の方に対しての補足です。ドリフト検出の仕組みが違うので注意が必要です。
CloudFormationのドリフト検出は、リソースの現在の状態とCloudFormationテンプレートの差分を比較する仕組みです。そのため、コードで定義していない部分はドリフト検出されないため、検出したいプロパティはコードで定義する必要があります。
詳しくは以下のブログをご覧ください。
Snyk IaCの場合
対して、Snyk IaCのドリフト検出ではリソースの現在の状態とtfstateファイルの差分を比較する仕組みです。「Terraformのコードとの差異ではない」ことに注意です。
tfstateファイルを比較対象とするため、定義していないプロパティもドリフト検出の対象になります。
「ドリフト検出」の出力結果を例にすると、「enable_dns_support
」はコードで定義されていないプロパティですが、検出結果に出力されています。
検出するプロパティはカスタマイズできる?
結論、カスタマイズ可能です。
ドリフト検出したくないリソースやプロパティに対して、次のように.snyk
ファイルを定義することでドリフト検出を回避できます。
次の例は、すべてのVPCリソースの「enable_dns_support
」プロパティをドリフト検出しない設定をしています。
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.25.0
ignore: {}
patch: {}
exclude:
iac-drift:
- aws_vpc.*.enable_dns_support
詳しくは以下リファレンスをご覧ください。
HTML出力もできる
snyk iac describe
コマンドは実行結果の出力方式にHTMLも対応しています。「--html-file-output
」オプションを指定することでHTMLファイル形式で結果を出力して確認できます。
snyk iac describe --drift --tf-provider-version=4.27.0 --html-file-output=result.html
エクスポートされた「result.html」を開くと次のようなファイルでドリフトを確認できます。「(computed)」が付いているプロパティは、コードで定義されていて検出されたプロパティになります。
コードで定義されて検知されたのか一目で判断できるため、.snyk
ファイルによる回避基準にとして良いなと思いました。
まとめ
以上、「Snyk IaCでTerraformのドリフト検出をやってみた」でした。
Terraformのドリフト基盤の手法の1つとして、とても使いやすいなと思いました。とくにコードで定義していない部分も検出できる点が個人的には大変魅力的でした。
以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!